package sg.edu.nus.iss.phoenix.maintainusers.controller;

import sg.edu.nus.iss.phoenix.authenticate.entity.Role;
import sg.edu.nus.iss.phoenix.authenticate.entity.User;
import sg.edu.nus.iss.phoenix.core.controller.FCUtilities;
import sg.edu.nus.iss.phoenix.core.controller.MessageBuilder;
import sg.edu.nus.iss.phoenix.maintainusers.delegate.UserDelegate;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * Created by A0119952X.
 */
@WebServlet("/MaintainUserController/*")
public class MaintainUserController extends HttpServlet {
    /**
     * processsing Get Request
     *
     * @param req
     * @param resp
     * @throws ServletException
     * @throws IOException
     */
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        processRequest(req, resp);
    }

    /**
     * processing POST request
     *
     * @param req
     * @param resp
     * @throws ServletException
     * @throws IOException
     */
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        processRequest(req, resp);
    }

    /**
     * constructor
     */
    public MaintainUserController() {
        super();
    }

    /**
     * process request method
     * check UI Input, parse data, redirect to suitable page
     *
     * @param request
     * @param response
     * @throws ServletException
     * @throws IOException
     */
    protected void processRequest(HttpServletRequest request,
                                  HttpServletResponse response) throws ServletException, IOException {
        String selection = FCUtilities.stripPath(request.getPathInfo())
                .toLowerCase();

        UserDelegate userDelegate = new UserDelegate();
        HttpSession session = request.getSession();
        User currentUser = (User) session.getAttribute("user");
        ArrayList<User> allUser = userDelegate.findAllUser();
        ArrayList<Role> availableRoles = userDelegate.findAllRoles();

        switch (selection) {
            case "changepassword":
                String oldPassword = request.getParameter("oldPassword");
                String newPassword = request.getParameter("newPassword");
                String confirmPassword = request.getParameter("confirmPassword");
                String message = "";

                if (!oldPassword.equals(currentUser.getPassword())) {
                    message = MessageBuilder.BuildMessage(MessageBuilder.MessageType.Error, "Old password not matched!");
                } else if (!newPassword.equals(confirmPassword)) {
                    message = MessageBuilder.BuildMessage(MessageBuilder.MessageType.Error, "New password not matched!");
                } else {
                    currentUser.setPassword(newPassword);
                    userDelegate.changePassword(currentUser);
                    message = MessageBuilder.BuildMessage(MessageBuilder.MessageType.Success, "Update successfully!");
                }

                request.setAttribute("message", message);
                RequestDispatcher rd = request
                        .getRequestDispatcher("/pages/changepassword.jsp");
                rd.forward(request, response);

                break;
            case "loadchangepassword":
                request.setAttribute("name", currentUser.getName());
                request.setAttribute("message", "");
                RequestDispatcher rd2 = request
                        .getRequestDispatcher("/pages/changepassword.jsp");
                rd2.forward(request, response);
                break;
            case "maintainuser":
                allUser = userDelegate.findAllUser();
                request.getSession().setAttribute("allUsers", allUser);
                RequestDispatcher rd3 = getServletContext().getRequestDispatcher("/pages/maintainuser.jsp");
                rd3.forward(request, response);
                break;
            case "addoredituser":
                String ins = request.getParameter("ins");
                boolean isInsert = ins.equalsIgnoreCase("true");
                String userId = request.getParameter("id");
                String name = request.getParameter("name");
                String password = request.getParameter("password");
                String[] roles = request.getParameterValues("selectedRoles");
                ArrayList<Role> userRoles = new ArrayList<Role>();

                if (userId.isEmpty()) {
                    message = MessageBuilder.BuildMessage(MessageBuilder.MessageType.Error, "User id cannot be empty");
                    request.setAttribute("message", message);
                    if (!isInsert) {
                        request.setAttribute("user", userDelegate.findUserByUserId(userId));
                    }
                    RedirectToAddUserPage(request, response, availableRoles, isInsert);
                    return;
                }

                if (name.isEmpty()) {
                    message = MessageBuilder.BuildMessage(MessageBuilder.MessageType.Error, "Name cannot be empty");
                    request.setAttribute("message", message);
                    if (!isInsert) {
                        request.setAttribute("user", userDelegate.findUserByUserId(userId));
                    }
                    RedirectToAddUserPage(request, response, availableRoles, isInsert);
                    return;
                }

                if (password.isEmpty()) {
                    message = MessageBuilder.BuildMessage(MessageBuilder.MessageType.Error, "Password cannot be empty");
                    request.setAttribute("message", message);
                    if (!isInsert) {
                        request.setAttribute("user", userDelegate.findUserByUserId(userId));
                    }
                    RedirectToAddUserPage(request, response, availableRoles, isInsert);
                    return;
                }

                if (roles.length == 0) {
                    message = MessageBuilder.BuildMessage(MessageBuilder.MessageType.Error, "Must have at least 1 role");
                    request.setAttribute("message", message);
                    if (!isInsert) {
                        request.setAttribute("user", userDelegate.findUserByUserId(userId));
                    }
                    RedirectToAddUserPage(request, response, availableRoles, isInsert);
                    return;
                }

                User user;
                if (isInsert) {
                    user = new User();
                    user.setId(userId);
                } else {
                    user = userDelegate.findUserByUserId(userId);
                }

                for (String roleName : roles) {
                    for (Role role : userDelegate.findAllRoles()) {
                        if (role.getRole().equals(roleName)) {
                            userRoles.add(role);
                        }
                    }
                }

                user.setName(name);
                user.setPassword(password);
                user.setRoles(userRoles);

                Logger.getLogger(getClass().getName()).log(Level.INFO, "Insert Flag: " + ins);

                boolean status;
                if (isInsert) {
                    status = userDelegate.insertUser(user);
                } else {
                    status = userDelegate.updateUser(user);
                }

                if (!status) {
                    message = MessageBuilder.BuildMessage(MessageBuilder.MessageType.Error, "Error happened");
                    request.setAttribute("message", message);
                } else {
                    message = MessageBuilder.BuildMessage(MessageBuilder.MessageType.Success, "Update successfully!");
                    request.setAttribute("message", message);
                }

                allUser = userDelegate.findAllUser();
                request.getSession().setAttribute("allUsers", allUser);
                RequestDispatcher rd4 = request.getRequestDispatcher("/pages/maintainuser.jsp");
                rd4.forward(request, response);
                break;
            case "adduser":
                RedirectToAddUserPage(request, response, availableRoles, true);
                break;
            case "edituser":
                ArrayList<Role> currentUserRoles = userDelegate.findUserByUserId(request.getParameter("id")).getRoles();

                for (Role role : currentUserRoles) {
                    availableRoles.remove(role);
                }

                request.setAttribute("user", userDelegate.findUserByUserId(request.getParameter("id")));
                RedirectToAddUserPage(request, response, availableRoles, false);
                break;
            case "deleteuser":
                userDelegate.deleteUser(userDelegate.findUserByUserId(request.getParameter("id")));
                allUser = userDelegate.findAllUser();
                request.getSession().setAttribute("allUsers", allUser);
                message = MessageBuilder.BuildMessage(MessageBuilder.MessageType.Success, "Update Successfully!");
                request.setAttribute("message", message);
                RequestDispatcher rd6 = request.getRequestDispatcher("/pages/maintainuser.jsp");
                rd6.forward(request, response);
                break;
            default:
                RequestDispatcher rd8 = request
                        .getRequestDispatcher("/pages/home.jsp");
                rd8.forward(request, response);
                break;
        }
    }

    /**
     * private helper method to redirect user to AddUser.jsp page
     *
     * @param request
     * @param response
     * @param availableRoles
     * @param isInsert
     * @throws ServletException
     * @throws IOException
     */
    private void RedirectToAddUserPage(HttpServletRequest request, HttpServletResponse response, ArrayList<Role> availableRoles, boolean isInsert) throws ServletException, IOException {
        request.setAttribute("availableRoles", availableRoles);
        RequestDispatcher rd = request
                .getRequestDispatcher(isInsert ? "/pages/adduser.jsp?insert=true" : "/pages/adduser.jsp");
        rd.forward(request, response);
    }
}
